package com.ocom.webapi.utils;

import org.apache.tomcat.util.codec.binary.Base64;
import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RsaUtil {


    public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
        // 获取指定算法的密钥对生成器（RSA）
        final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器（指定密钥长度, 使用默认的安全随机数源）
        generator.initialize(keySize);
        // 随机生成一对密钥（包含公钥和私钥）
        return generator.generateKeyPair();
    }

    /**
     * RSA 加密
     *
     * @param publicKeyBytes 公钥
     * @param plain          原文
     * @return　密文
     */
    public static byte[] encrypt(byte[] publicKeyBytes, byte[] plain) throws Exception {
        // RSA
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(publicKeyBytes);
        final PublicKey publicKey = keyFactory.generatePublic(pubX509);
        final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plain);
    }

    /**
     * RSA 解密
     *
     * @param privateKeyBytes 　私钥
     * @param encrypted       　密文
     * @return　byte[] 原文
     */
    public static byte[] decrypt(byte[] privateKeyBytes, byte[] encrypted) throws Exception {
        // RSA
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        final PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encrypted);
    }

    /**
     * signature.
     *
     * @param privateKeyBytes 私钥
     * @param plain           明文
     * @return String 签名
     */
    public static String signature(byte[] privateKeyBytes, String plain) throws Exception {
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        final PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        final Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(plain.getBytes(StandardCharsets.UTF_8));
        final byte[] signed = signature.sign();
        return Base64.encodeBase64URLSafeString(signed);
    }

    /**
     * verify.
     *
     * @param publicKeyBytes 公钥
     * @param plain          原文
     * @param sign           签名
     * @return boolean
     */
    public static boolean verify(byte[] publicKeyBytes, String plain, String sign)
            throws Exception {
        final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        final X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(publicKeyBytes);
        final PublicKey publicKey = keyFactory.generatePublic(pubX509);
        final Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(plain.getBytes(StandardCharsets.UTF_8));
        return signature.verify(Base64.decodeBase64URLSafe(sign));
    }

    public static void main(String[] args) throws Exception {
        final String data = "test";
        final KeyPair keyPair = generateKeyPair(2048);

        final byte[] encrypt = encrypt(keyPair.getPublic().getEncoded(), data.getBytes());
        final byte[] decrypt = decrypt(keyPair.getPrivate().getEncoded(), encrypt);
        System.out.println(new String(decrypt));


        final String data2 = "test";
        final KeyPair keyPair2 = generateKeyPair(2048);

        final String sign = signature(keyPair2.getPrivate().getEncoded(), data2);
        final boolean verify = verify(keyPair2.getPublic().getEncoded(), data2, sign);
        System.err.println(verify);

        //28FA71C24AAC02950010D21D56488222       华兴
        
        String currentUuid = "28FA71C24AAC02950010D21D56488222";

        String privateKeyString = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/BCgcdyIA0AQW54rTDokOyaiCLEZR1jvrAN+b8WFOigxPDpy4/+zbGAWb0IriAytx//0FWZqjah8UTU5jQRo4ZhhNjn66l207nmxqviZcs0gmPJe1d7OfmP3KPzZlZI0t5YjQMpbV/v0rNnUnYQ2vArjzgnPdbuFnpFCRIiaxiuIZ+uLE21mGeGPYv5DX6roPbBHUs48DfvJ47SNhcZwzhRodrNlFZiXFz2XO9Pa4dXUoPnv9MAzguenWcTVRyuWl5astmCZ1UDQtGABpB1Ul8RcEL7TO8goDhHLW0Rn352XS7zcGUdvSHPVDLoyhg8jt2TBOPi1RP9X1qM5/9kYpAgMBAAECggEBAL0Pfiv+djdbrFCHSE5x2pI6YoDFFay2YIPPT4NnvCoiVOCC0/f/xw1rj1GTbYMaJAwnlOWQtI/931kW0vlGXI9p7bAF08UXT9Rsj15vakTiZg0CeB3ypmTW5oshWdOtXFcLEwkOqWCRiz8UHYymcQbBqRHMEqYesxcD+YJMzQN3fzVhNy5EAVH1osv5aOGfQZ0f/zuerpvwnKiS1xxCTFO0+c9eWdt1teRPA5RCjFSWMCOJOEpui6eSUb8fj//YscSSlBgeAV7AxWrKm31xEOnRm0d2j5WPP2SX8tL9oPoBv8ypl13zw1ZdU2Icf1n4UdHy/MogeLyGU7/ntX8FKQkCgYEA49zLpI5c3DTAu+8wxa0OTh78St20OS6rAswKsq3DKHMbs8W8G7x1vqHRmbezue8wWLyv5tZE/e340hPPeAiIgPeclvIu7q2VxHkJNFixMKg0nEIVF2XtdNZtNslr8SaXh8Z9aw6XY365jhQDnLyusjWGCWVhEIETzYvPuUz0gdMCgYEA1pqTPVzJhhzEHcRlU8ljLWJWQ9YxkRE80ZLq+1+CwMwMjdTxvOuE1kTQzG7gbtci4h08PdK11ZBz2EUFr75oTEUhhgqTTnJKsROWy7dgw/AnaYXtR7ac1K93G41ltkv0Hh21l16GYLNuGW48HWNuwRn56p/5FScgjBQ1faWjHpMCgYEA33e93B+mYGv4DRfynBsxaVooEgBGbMIhAvg7EasqN3RUWcV1yznTu+aVWgz4XUSABLbgSCIhvWtyWA0Hrm+n99tfHgZcEsX4mJwfc8/7zn1YQ1rntm/HJovYxh9aFkHD4GvAuoqv2+r/baChPkkphyrIzlQ3kmkUk8QnL1KShPMCgYBe5/dLwNgipmAY5f0Fw99Hd+C8mWJMTHpAGKAw0PlrOBIpO045BVM2yzIn5rT8b8oug01b7e6aZwrETyoHocZQTJZZyB2DKMpda1NZ/lwd6vwTD7Zy65CKAptDJRIhP4/TLcJcEeKNq2x6dKTDPnEBlvJOT7cBIs+jA2DwkysDXwKBgQCj3TZEvJohhzUO/Xie5RDk1tXRhPNSjUAjDUn4uFUrbU1U8JygRMYkC3qIL6X8TJyH+Baf0iIVsOv2wmipff8vGWKEMiRzjMbX9KoEWNIy1p2vd+xR/Beto+H0Yt+xW/nuTKDQddra1GqKND0kxwrxCcKTWDGSk5AtaM9TDwSjcA==";
        String publicKeyString = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwQoHHciANAEFueK0w6JDsmogixGUdY76wDfm/FhTooMTw6cuP/s2xgFm9CK4gMrcf/9BVmao2ofFE1OY0EaOGYYTY5+updtO55sar4mXLNIJjyXtXezn5j9yj82ZWSNLeWI0DKW1f79KzZ1J2ENrwK484Jz3W7hZ6RQkSImsYriGfrixNtZhnhj2L+Q1+q6D2wR1LOPA37yeO0jYXGcM4UaHazZRWYlxc9lzvT2uHV1KD57/TAM4Lnp1nE1UcrlpeWrLZgmdVA0LRgAaQdVJfEXBC+0zvIKA4Ry1tEZ9+dl0u83BlHb0hz1Qy6MoYPI7dkwTj4tUT/V9ajOf/ZGKQIDAQAB";
        System.out.println("privateKeyString:"+privateKeyString);
        System.out.println("publicKeyString:"+publicKeyString);

        final String sign3 = signature(getPrivateKey(privateKeyString).getEncoded(), currentUuid);
        final boolean verify3 = verify(getPublicKey(publicKeyString).getEncoded(), currentUuid, sign3);
        System.out.println("主板签名:"+sign3);
        System.err.println(verify3);


    }


    /**
     * 使用getPublicKey得到公钥,返回类型为PublicKey
     *
     * @param base64 String to PublicKey
     * @throws Exception
     */
    public static PublicKey getPublicKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 转换私钥
     *
     * @param base64 String to PrivateKey
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }


    /**
     privateKeyString:MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/BCgcdyIA0AQW54rTDokOyaiCLEZR1jvrAN+b8WFOigxPDpy4/+zbGAWb0IriAytx//0FWZqjah8UTU5jQRo4ZhhNjn66l207nmxqviZcs0gmPJe1d7OfmP3KPzZlZI0t5YjQMpbV/v0rNnUnYQ2vArjzgnPdbuFnpFCRIiaxiuIZ+uLE21mGeGPYv5DX6roPbBHUs48DfvJ47SNhcZwzhRodrNlFZiXFz2XO9Pa4dXUoPnv9MAzguenWcTVRyuWl5astmCZ1UDQtGABpB1Ul8RcEL7TO8goDhHLW0Rn352XS7zcGUdvSHPVDLoyhg8jt2TBOPi1RP9X1qM5/9kYpAgMBAAECggEBAL0Pfiv+djdbrFCHSE5x2pI6YoDFFay2YIPPT4NnvCoiVOCC0/f/xw1rj1GTbYMaJAwnlOWQtI/931kW0vlGXI9p7bAF08UXT9Rsj15vakTiZg0CeB3ypmTW5oshWdOtXFcLEwkOqWCRiz8UHYymcQbBqRHMEqYesxcD+YJMzQN3fzVhNy5EAVH1osv5aOGfQZ0f/zuerpvwnKiS1xxCTFO0+c9eWdt1teRPA5RCjFSWMCOJOEpui6eSUb8fj//YscSSlBgeAV7AxWrKm31xEOnRm0d2j5WPP2SX8tL9oPoBv8ypl13zw1ZdU2Icf1n4UdHy/MogeLyGU7/ntX8FKQkCgYEA49zLpI5c3DTAu+8wxa0OTh78St20OS6rAswKsq3DKHMbs8W8G7x1vqHRmbezue8wWLyv5tZE/e340hPPeAiIgPeclvIu7q2VxHkJNFixMKg0nEIVF2XtdNZtNslr8SaXh8Z9aw6XY365jhQDnLyusjWGCWVhEIETzYvPuUz0gdMCgYEA1pqTPVzJhhzEHcRlU8ljLWJWQ9YxkRE80ZLq+1+CwMwMjdTxvOuE1kTQzG7gbtci4h08PdK11ZBz2EUFr75oTEUhhgqTTnJKsROWy7dgw/AnaYXtR7ac1K93G41ltkv0Hh21l16GYLNuGW48HWNuwRn56p/5FScgjBQ1faWjHpMCgYEA33e93B+mYGv4DRfynBsxaVooEgBGbMIhAvg7EasqN3RUWcV1yznTu+aVWgz4XUSABLbgSCIhvWtyWA0Hrm+n99tfHgZcEsX4mJwfc8/7zn1YQ1rntm/HJovYxh9aFkHD4GvAuoqv2+r/baChPkkphyrIzlQ3kmkUk8QnL1KShPMCgYBe5/dLwNgipmAY5f0Fw99Hd+C8mWJMTHpAGKAw0PlrOBIpO045BVM2yzIn5rT8b8oug01b7e6aZwrETyoHocZQTJZZyB2DKMpda1NZ/lwd6vwTD7Zy65CKAptDJRIhP4/TLcJcEeKNq2x6dKTDPnEBlvJOT7cBIs+jA2DwkysDXwKBgQCj3TZEvJohhzUO/Xie5RDk1tXRhPNSjUAjDUn4uFUrbU1U8JygRMYkC3qIL6X8TJyH+Baf0iIVsOv2wmipff8vGWKEMiRzjMbX9KoEWNIy1p2vd+xR/Beto+H0Yt+xW/nuTKDQddra1GqKND0kxwrxCcKTWDGSk5AtaM9TDwSjcA==

     publicKeyString:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwQoHHciANAEFueK0w6JDsmogixGUdY76wDfm/FhTooMTw6cuP/s2xgFm9CK4gMrcf/9BVmao2ofFE1OY0EaOGYYTY5+updtO55sar4mXLNIJjyXtXezn5j9yj82ZWSNLeWI0DKW1f79KzZ1J2ENrwK484Jz3W7hZ6RQkSImsYriGfrixNtZhnhj2L+Q1+q6D2wR1LOPA37yeO0jYXGcM4UaHazZRWYlxc9lzvT2uHV1KD57/TAM4Lnp1nE1UcrlpeWrLZgmdVA0LRgAaQdVJfEXBC+0zvIKA4Ry1tEZ9+dl0u83BlHb0hz1Qy6MoYPI7dkwTj4tUT/V9ajOf/ZGKQIDAQAB

     Process finished with exit code 0

     */


}
